﻿-- простой фильтр спама

SsfDebug = false

local SpamPatterns = {
    'печень',
    'vipshop',
    'овощевик',
    'яндекс',
    'skype',
    'qiwi',
    'скайп',
    'icq',
    'аська',
    'ася',
    'продам {круг}',
    'продам{круг}',
    '{круг} по',
    'куплю{круг}',
    'куплю {круг}',
    'поможем с ',
    'помогу с ',
    'rpgbox',
    'money',
    'silkcadr',
    'dving.ru',
    'gameplanet',
    'блестя',
    'snuffc',
    'deal',
    'pay',
    'фани-мани',
    '.рф',
    '.РФ',
    '.ru',
    'arena',
    'servi',
    'eubattle',
    'zoloto',
    'gvino',
    'рбг',
    'арен',
    'рпб',
    '2х2', '2x2',
    '3х3', '3x3',
    '5х5', '5x5',
}

CustomSpamPatterns = {}

ChatMonitorPatterns = {}
ChatMonitorBlacklisted = {}
ChatMonitorDisabled = false

local BlackListed = {} -- key = nick, value = true

local disabled = false

local last_line_id = -1
local last_result = nil
local last_channel_id = nil

local MIN_REPEAT_INTERVAL = 60 -- seconds
local history = {} -- key -- line, value -- timestamp
local last_history_purge_time = 0
local HISTORY_PURGE_INTERVAL = 65

local MyName = UnitName('player')

local LastMonSoundTime = 0

local function TRADE_FILTER(_, event, chat_line, player, _, _, _, flag, channelId, _, _, _, line_id)
    if disabled then
        return
    end

    if (last_line_id == line_id) and (last_channel_id == channelId) then
        return last_result
    end

    last_line_id = line_id
    last_channel_id = channelId
    last_result = nil

    if player == MyName then
        return
    end

    if BlackListed[player] then
        if SsfDebug then
            print('SSF BLACKLISTED: ', player)
        end
        last_result = true
        return true
    end

    local line = chat_line:lower()

    for _, pattern in ipairs(SpamPatterns) do
        if line:find(pattern) then
            if SsfDebug then
                print('SSF FILTERED OUT(', pattern, '): ', chat_line)
            end
            BlackListed[player] = true
            last_result = true
            return true
        end
    end

    for _, pattern in ipairs(CustomSpamPatterns) do
        if line:find(pattern) then
            if SsfDebug then
                print('SSF FILTERED OUT (', pattern, '): ', chat_line)
            end
            BlackListed[player] = true
            last_result = true
            return true
        end
    end

    local now = GetTime()

    local ts = history[line]
    if not ts then
        history[line] = now
    else
        if (now - ts) < MIN_REPEAT_INTERVAL then
            last_result = true
            return true
        end
        history[line] = now -- allow line, set new timestamp
    end

    if (GetTime() - last_history_purge_time) >= HISTORY_PURGE_INTERVAL then
        last_history_purge_time = GetTime()
        local to_remove = {}
        for line, ts in pairs(history) do
            if (GetTime() - ts) > MIN_REPEAT_INTERVAL then
                tinsert(to_remove, line)
            end
        end
        for _, line in ipairs(to_remove) do
            history[line] = nil
        end
    end

    -- monitor
    if not ChatMonitorDisabled and not ChatMonitorBlacklisted[player] then
        for _, words in ipairs(ChatMonitorPatterns) do
            local found = false
            local skip = false

            if type(words) == 'string' then
                -- one regex
                found = line:find(words)
            else
                -- collection of regexes
                for _, pattern in ipairs(words) do
                    if not skip then
                        local start = pattern:sub(1, 1)
                        if start == '!' then
                            skip = line:find(pattern:sub(2))
                        elseif start == '&' then
                            skip = line:find(pattern:sub(2)) == nil
                        elseif line:find(pattern) then
                            found = true
                        end
                    end
                end
            end

            if found and not skip then
                local t = date('*t')
                local ts = ''
                if t.hour < 10 then
                    ts = '0'
                end
                ts = ts..t.hour..':'
                if t.min < 10 then
                    ts = ts..'0'
                end
                ts = ts..t.min
                DEFAULT_CHAT_FRAME:AddMessage(ts..' ['..player..']: '..chat_line)
                if (GetTime() - LastMonSoundTime) > 10 then
                    PlaySoundFile([[Interface\Addons\ps\media\NeoBeep.mp3]], 'Master')
                    LastMonSoundTime = GetTime()
                end
            end
        end
    end
end
ChatFrame_AddMessageEventFilter('CHAT_MSG_CHANNEL', TRADE_FILTER)
ChatFrame_AddMessageEventFilter('CHAT_MSG_YELL', TRADE_FILTER)

-- command line support
local SlashCmdList = _G['SlashCmdList']
SlashCmdList['SSF'] = function(cmd)
    if cmd == 'off' or cmd == 'disable' then
        if not disabled then
            disabled = true
            print('SimpleSpamFilter disabled')
        end
    elseif cmd == 'on' or cmd == 'enable' then
        if disabled then
            disabled = false
            print('SimpleSpamFilter enabled')
        end
    else
        for _, pattern in ipairs(CustomSpamPatterns) do
            if pattern == cmd then
                return -- already in list
            end
        end
        tinsert(CustomSpamPatterns, cmd)
    end
end
_G['SLASH_SSF1'] = '/ssf'
----------------------------------------
SlashCmdList['CMON'] = function(cmd_line)
    if cmd_line == '' then
        local status
        if ChatMonitorDisabled then
            status = 'off'
        else
            status = 'on'
        end
        print('Chat monitor status: ', status)
        if #ChatMonitorPatterns == 0 then
            print('Monitoring patterns not defined')
        else
            print('Patterns:')
            for _, patterns in pairs(ChatMonitorPatterns) do
                if type(patterns) == 'string' then
                    print('  %', patterns)
                else
                    print('  ', unpack(patterns))
                end
            end
        end
    elseif cmd_line[1] == '%' then
        tinsert(ChatMonitorPatterns, cmd_line:sub(2)) -- regex
    elseif cmd_line == 'off' then
        if ChatMonitorDisabled then
            ChatMonitorDisabled = false
            print('Chat Monitor enabled')
        else
            ChatMonitorDisabled = true
            print('Chat Monitor disabled')
        end
    elseif cmd_line == 'clear' then
        ChatMonitorPatterns = {}
        print('Chat Monitor paterns cleared')
    else
        local args = {strsplit(' ', (cmd_line or ''):lower())}
        if args[1] == 'ignore' then
            if ChatMonitorBlacklisted[args[2]] then
                ChatMonitorBlacklisted[args[2]] = nil
                print(player, ' removed from ChatMonitor blacklist')
            else
                ChatMonitorBlacklisted[args[2]] = true
                print(player, ' added to ChatMonitor blacklist')
            end
        else
            tinsert(ChatMonitorPatterns, args)
            print('ChatMonitor: added pattern '..cmd_line)
        end
    end
end
--[[
patterns:
word !word &words
no prefix -- one of such words must be in chat line
! -- word should not be in chat line
& -- word must be in chat line
--]]
_G['SLASH_CMON1'] = '/cmon'
